#include <stdio.h>
#include <stdlib.h>

typedef int HElemSet;
typedef int Position; /* 数组下标即为元素位置 */
typedef struct BinaryHeapNode *MaxHeap;
typedef struct BinaryHeapNode *MinHeap;
struct BinaryHeapNode {
    HElemSet *data; /* 数据元素数组 */
    int size; /* 规模 */
    int capacity; /* 容量 */
};

void InitPQueue(MinHeap pq, int capacity);
void SiftUp(MinHeap h, Position i);
void SiftDown(MinHeap h, Position i);
void Insert(MinHeap h, HElemSet x);
HElemSet ExtractMin(MinHeap h);

int main(void) {
    MinHeap h;
    int capacity, n, i;
    HElemSet x;

    h = (MinHeap)malloc(sizeof(struct BinaryHeapNode));
    scanf("%d", &capacity);
    InitPQueue(h, capacity);
    scanf("%d", &n);
    h->size = n;
    for (i = 1; i <= n; i++) {
        scanf("%d", &h->data[i]); /* 读入一个最小堆 */
    }
    scanf("%d", &x);
    Insert(h, x);
    printf("min = %d\n", ExtractMin(h));
    for (i = 1; i <= h->size; i++) { /* 输出插入、删除后的堆元素 */
        printf("%d\n", h->data[i]);
    }
    return 0;
}

void InitPQueue(MinHeap pq, int capacity) {
    pq->capacity = capacity;
    pq->size = 0;
    /* 数据从下标1开始存储，需要多声明1个空间 */
    pq->data = (HElemSet *)malloc(sizeof(HElemSet) * (capacity + 1));
}

/* 算法6-1：二叉堆的上调操作 SiftUp(h, i) */
void SiftUp(MinHeap h, Position i) {
    HElemSet elem;

    elem = h->data[i];
    while (i > 1 && elem < h->data[i >> 1]) { /* 当前结点小于其父结点 */
        h->data[i] = h->data[i >> 1]; /* 将i的父结点元素下移 */
        i >>= 1; /* i指向原结点的父结点，即向上调整 */
    }
    h->data[i] = elem;
}
/* 算法6-1 结束 */

/* 算法6-2：二叉堆的下调操作 SiftDown(h, i) */
void SiftDown(MinHeap h, Position i) {
    Position last, child;
    HElemSet elem;

    last = h->size; /* 这是最后一个元素的位置 */
    elem = h->data[i];
    while (1) {
        child = i << 1; /* child当前是i的左孩子的位置 */
        if (child < last
                && h->data[child + 1] < h->data[child]) { /* 如果i有右孩子并且右孩子更小 */
            child++; /* child更新为i的右孩子的位置 */
        } else if (child > last) { /* 如果i是叶子结点 */
            break; /* 已经调整到底，跳出循环 */
        }
        if (h->data[child] < elem) { /* 若较小的孩子比elem小 */
            h->data[i] = h->data[child]; /* 将较小的孩子结点上移 */
            i = child; /* i指向原结点的孩子结点，即向下调整 */
        } else { /* 若所有孩子都不比elem小 */
            break; /* 则找到了elem的最终位置，跳出循环 */
        }
    }
    h->data[i] = elem;
}
/* 算法6-2 结束 */

/* 算法6-3：二叉堆的插入操作 Insert(h, x) */
void Insert(MinHeap h, HElemSet x) {
    Position last;

    if (h->size == h->capacity) { /* 堆已满 */
        printf("错误：堆已满，无法插入。\n");
    } else {
        h->size++;
        last = h->size;
        h->data[last] = x; /* 暂时将x放入最后一个元素的位置 */
        SiftUp(h, last);
    }
}
/* 算法6-3 结束 */

/* 算法6-4：二叉堆的删顶操作 ExtractMin(h) */
HElemSet ExtractMin(MinHeap h) {
    HElemSet min_key;
    Position last;

    min_key = h->data[1]; /* 这是将要返回的最小元 */
    last = h->size; /* 这是删除前最后一个元素的位置 */
    h->size--;
    h->data[1] =
        h->data[last]; /* 暂时将删除前最后一个元素放入根的位置 */
    SiftDown(h, 1); /* 从根结点下调 */
    return min_key;
}
/* 算法6-4 结束 */